//
//  NativeOSSChannel.m
//  Runner
//
//  Created by wtb on 2023/3/2.
//

#import "NativeOSSChannel.h"
#import "KqOssManager.h"
#import "KqImageTool.h"
#import "KqTool.h"

static NSString *const channelName = @"flutter.keqiang.com/oss";
//下载图片
static NSString *const ossDownloadImage = @"ossDownloadImage";
//上传图片
static NSString *const ossUploadImage = @"ossUploadPics";
//单个上传文件到OSS
static NSString *const ossUploadFile = @"ossUploadFile";
//阿里云删除图片
static NSString *const ossDelete = @"ossDelete";
//阿里云取消下载
static NSString *const ossCancelDownload = @"ossCancelDownload";
//获取缓存
static NSString *const getOssCacheFile = @"getOssCacheFile";
//初始化配置
static NSString *const ossInit = @"initOSS";
@implementation NativeOSSChannel


+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar{
    FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:channelName binaryMessenger:[registrar messenger]];
    NativeOSSChannel *oss = [[NativeOSSChannel alloc] init];
//    oss.load = [[FastLoad alloc] initWithMaxQueueCount:15];
    [registrar addMethodCallDelegate:oss channel:channel];

//    // 文件上传进度通知
    FlutterEventChannel *eventChannel = [FlutterEventChannel eventChannelWithName:@"flutter.keqiang.com/ossEvent" binaryMessenger:[registrar messenger]];
    oss.event = [[NativeOSSEventChannel alloc] init];
    [eventChannel setStreamHandler:oss.event];
}

-(void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result{
    NSString *ossKey = call.arguments[@"ossKey"];
    if ([ossDownloadImage isEqualToString:call.method]) {
        if (!ossKey) {
            NSMutableDictionary *res = [NSMutableDictionary dictionary];
            [res setValue:@0 forKey:@"code"];
            [res setValue:@"ossKey is Empty" forKey:@"msg"];
            result(res);
        }else{
            //下载
            int picWidth = [self getImageWidth:call.arguments];
            int picHeight = [self getImageHeight:call.arguments];
            NSDictionary *info = [self getCacheFileInfo:ossKey arguments:call.arguments];
            if(info){
                result(info);
            }else{
                [[KqOssManager defaultKqOssManager] downLoadImage:ossKey picWidth:picWidth picHeight:picHeight tag:call.arguments[@"tag"] callback:^(NSDictionary * _Nonnull uri) {
                    NSMutableDictionary *res = [NSMutableDictionary dictionary];
                    if (uri) {
                        [res setValue:@1 forKey:@"code"];
                        [res setValue:uri forKey:@"data"];
                    }else{
                        [res setValue:@0 forKey:@"code"];
                        [res setValue:@"下载失败" forKey:@"msg"];
                    }
                    result(res);
                }];
            }
        }
    }else if([ossUploadImage isEqualToString:call.method]){
        NSArray *list = call.arguments[@"ossKeyAndPaths"];
        NSMutableArray *uploadResults = [NSMutableArray array];
        dispatch_group_t group = dispatch_group_create();
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        for (NSDictionary *dic in list) {
            NSMutableDictionary *resultDic = [NSMutableDictionary dictionaryWithDictionary:dic];
            [uploadResults addObject:resultDic];
            if ([[dic objectForKey:@"uploadOk"] isEqual:@1]) {
                //已经上传成功，则不再上传
                continue;
            }
            dispatch_group_enter(group);
            
            NSString *objectKey = [dic objectForKey:@"objectKey"];
            NSString *imagePath = [dic objectForKey:@"filePath"];
            NSData *imageData = [NSData dataWithContentsOfFile:imagePath];
            //压缩图片
            NSData *compressData = [KqImageTool kqQualityCompressData:imageData];
            
            if (!objectKey) {
                objectKey = [dic objectForKey:@"ossKey"];
            }
            dispatch_group_async(group, queue, ^{
                [[KqOssManager defaultKqOssManager] uploadImage:compressData objectKey:objectKey callback:^(BOOL success) {
                    if(success){
                        [resultDic setValue:[NSNumber numberWithBool:success] forKey:@"uploadOk"];
                        //大小
                        NSUInteger size = compressData.length;
                        [resultDic setValue:[NSNumber numberWithInteger:size] forKey:@"fileSize"];
                        
                        NSString *type = [[objectKey componentsSeparatedByString:@"."] lastObject];
                        //文件名
                        NSString *fileName = [NSString stringWithFormat:@"%@.%@",[KqTool stringToMd5:[NSString stringWithFormat:@"%@_%lu",objectKey,(unsigned long)size]],type];
                        [resultDic setValue:fileName forKey:@"fileName"];
                    }
                    
                    dispatch_group_leave(group);
                }];
            });
        }
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            result(uploadResults);
        });
    }else if([ossUploadFile isEqualToString:call.method]){
        //单个上传文件到OSS，通过通道[flutter.keqiang.com/ossEvent]监听上传进度，用[tag]区分文件
        NSString *tag = call.arguments[@"tag"];
        NSString *objectKey = call.arguments[@"ossKey"];
        NSString *filePath = call.arguments[@"filePath"];
        NSData *fileData = [NSData dataWithContentsOfFile:filePath];
        __weak __typeof(self)weakSelf = self;
        [[KqOssManager defaultKqOssManager] uploadFile:fileData objectKey:objectKey progress:^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
            dispatch_sync(dispatch_get_main_queue(), ^{
                NSMutableDictionary *progressDic = [NSMutableDictionary dictionary];
                [progressDic setValue:[NSNumber numberWithInteger:totalBytesExpectedToSend] forKey:@"totalSize"];
                [progressDic setValue:[NSNumber numberWithInteger:totalBytesSent] forKey:@"currentSize"];
                [progressDic setValue:tag forKey:@"tag"];
                if(weakSelf.event.eventSink){
                    weakSelf.event.eventSink(progressDic);
                }
            });
        } tag:tag callback:^(BOOL success) {
            NSMutableDictionary *res = [NSMutableDictionary dictionary];
            if (success) {
                [res setValue:@1 forKey:@"code"];
            }else{
                [res setValue:@0 forKey:@"code"];
            }
            result(res);
        }];
    }else if([ossDelete isEqualToString:call.method] && ossKey){
        //删除
        [KqOssManager deleteImage:ossKey callback:^(BOOL success) {
            NSMutableDictionary *res = [NSMutableDictionary dictionary];
            if (success) {
                [res setValue:@1 forKey:@"code"];
            }else{
                [res setValue:@0 forKey:@"code"];
            }
            result(res);
        }];
    }else if ([ossCancelDownload isEqualToString:call.method]){
        //取消下载
        [KqOssManager cancel:call.arguments[@"tag"]];
        NSMutableDictionary *res = [NSMutableDictionary dictionary];
        [res setValue:@1 forKey:@"code"];
        result(res);
    }else if ([ossInit isEqualToString:call.method]){
        NSString *bucketName = call.arguments[@"bucketName"];
        if(bucketName && [bucketName isEqualToString:@"gofactory4test"]){
            [[KqOssManager defaultKqOssManager] setOssBucketNameFromEnv:false];
        }else{
            [[KqOssManager defaultKqOssManager] setOssBucketNameFromEnv:true];
        }
    }else if([getOssCacheFile isEqualToString:call.method]){
        NSDictionary *info = [self getCacheFileInfo:ossKey arguments:call.arguments];
        if(info){
            result(info);
        }else{
            result(@{@"code":@0,@"msg":[NSString stringWithFormat:@"%@没有缓存",ossKey]});
        }
    }
}


-(NSDictionary *)getCacheFileInfo:(NSString *)ossKey arguments:(id)arguments{
    int picWidth = [self getImageWidth:arguments];
    int picHeight = [self getImageHeight:arguments];
    
    NSString *type = [[ossKey componentsSeparatedByString:@"."] lastObject];
    NSString *fileName = [NSString stringWithFormat:@"%@",[KqTool stringToMd5:[NSString stringWithFormat:@"%@_%d_%d",ossKey,picWidth,picHeight]]];
    
    NSString *filePath = [KqTool findImageToTmpFolder:fileName];
    if(filePath){
        NSData *imgData = [NSData dataWithContentsOfFile:filePath];
        NSUInteger size = imgData.length;
        NSString *type = [[filePath componentsSeparatedByString:@"."] lastObject];
        NSMutableDictionary *uri = [NSMutableDictionary dictionary];
        [uri setValue:filePath forKey:@"filePath"];
        [uri setValue:[NSNumber numberWithInteger:size] forKey:@"fileSize"];
        [uri setValue:[NSString stringWithFormat:@"image/%@",type] forKey:@"fileMime"];
        [uri setValue:fileName forKey:@"fileName"];
        NSMutableDictionary *res = [NSMutableDictionary dictionary];
        [res setValue:@1 forKey:@"code"];
        [res setValue:uri forKey:@"data"];
        return res;
    }
    return nil;
}

-(int)getImageWidth:(id)arguments{
    int picWidth = 0;
    if (arguments[@"width"] && ![arguments[@"width"] isEqual:[NSNull null]]) {
        picWidth = [arguments[@"width"] intValue];
    }
    return picWidth;
}

-(int)getImageHeight:(id)arguments{
    int picHeight = 0;
    if (arguments[@"height"] && ![arguments[@"height"] isEqual:[NSNull null]]) {
        picHeight = [arguments[@"height"] intValue];
    }
    return picHeight;
}
//- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(FlutterEventSink)eventSink {
//    self.eventSink = eventSink;
//    return nil;
//}
//
//- (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments {
//    self.eventSink = nil;
//    return nil;
//}

@end

@implementation NativeOSSEventChannel

-(void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result{}
- (FlutterError * _Nullable)onCancelWithArguments:(id _Nullable)arguments {
    self.eventSink = nil;
    return nil;
}

- (FlutterError * _Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(nonnull FlutterEventSink)events {
    self.eventSink = events;
    return nil;
}

@end
